﻿//  DTLZ7.cs
//
//  Author:
//       Antonio J. Nebro <antonio@lcc.uma.es>
//
//  Copyright (c) 2011 Antonio J. Nebro
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
// 
//  You should have received a copy of the GNU Lesser General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using jmetal.core;
using jmetal.encodings.solutionType;

namespace jmetal.problems
{
  public class DTLZ7 : Problem
  {

    public DTLZ7(String solutionType)
      : this(solutionType, 22, 3)
    {
    } // DTLZ1

    /**
     * Creates a new instance of problem DTLZ7.
     * @param numberOfVariables Number of variables.     
     * @param numberOfObjectives Number of objectives.
     * @param solutionType The solution type must "Real", "BinaryReal, and "ArrayReal". 
     */
    public DTLZ7(String solutionType, int numberOfVariables, int numberOfObjectives)
    {
      numberOfVariables_ = numberOfVariables;
      numberOfObjectives_ = numberOfObjectives;
      numberOfConstraints_ = 0;
      problemName_ = "DTLZ7";

      upperLimit_ = new double[numberOfVariables_];
      lowerLimit_ = new double[numberOfVariables_];

      // Establishes upper and lower limits for the variables
      for (int var = 0; var < numberOfVariables_; var++)
      {
        lowerLimit_[var] = 0.0;
        upperLimit_[var] = 1.0;
      } // for

      solutionType_ = new RealSolutionType(this);
    } // DTLZ7


    /// <summary>
    /// Evaluates a solution
    /// </summary>
    /// <param name="solution">Solution to evaluate</param>
    public override void evaluate(Solution solution)
    {
      // <pex>
      if (solution == (Solution)null)
        throw new ArgumentNullException("solution");
      if (solution.variable_ == (Variable[])null)
        throw new ArgumentNullException("solution");
      // </pex>
      Variable[] vars = solution.variable_;

      double[] f = new double[numberOfObjectives_];
      double[] x = new double[numberOfVariables_];

      int k = numberOfVariables_ - numberOfObjectives_ + 1;

      for (int i = 0; i < numberOfVariables_; i++)
        x[i] = vars[i].value_;

      double g = 0.0;
      for (int i = this.numberOfVariables_ - k; i < numberOfVariables_; i++)
        g += x[i];

      g = 1 + (9.0 * g) / k;
      //<-

      //Calculate the value of f1,f2,f3,...,fM-1 (take acount of vectors start at 0)
      for (int i = 0; i < numberOfObjectives_ - 1; i++)
        f[i] = x[i];
      //<-

      //->Calculate fM
      double h = 0.0;
      for (int i = 0; i < numberOfObjectives_ - 1; i++)
        h += (f[i] / (1.0 + g)) * (1 + Math.Sin(3.0 * Math.PI * f[i]));

      h = numberOfObjectives_ - h;

      f[numberOfObjectives_ - 1] = (1 + g) * h;

      for (int i = 0; i < numberOfObjectives_; i++)
        solution.objective_[i] = f[i];
    } // evaluate
  }
}
